package com.zs.toolbox.web2j.auth.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zs.toolbox.web2j.auth.domain.WtLoginRequest;
import com.zs.toolbox.web2j.auth.utils.WtTokenUtils;
import com.zs.toolbox.web2j.common.config.WtConfigUtil;
import com.zs.toolbox.web2j.common.response.WtBaseResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.zs.toolbox.web2j.auth.contants.WtSecurityConstant.TokenFieldName;

/**
 * @author shuai.zhang  on 2018/9/13
 * @version 1.0.0
 * @description 主要用来负责登陆使用
 * @deprecated  直接在controller层做登陆处理
 */
public class WtJWTLoginFilter extends UsernamePasswordAuthenticationFilter {
    private static Logger logger = LoggerFactory.getLogger(WtJWTLoginFilter.class);

    private AuthenticationManager authenticationManager;

    public WtJWTLoginFilter(AuthenticationManager authenticationManager) {

        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(WtConfigUtil.conf().getString("wt.security.token.login.url")));
        this.authenticationManager = authenticationManager;
    }


    /**
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     * @description 从上下文中解析出用户名及密码 并生成校验对象
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        try {

            WtLoginRequest user = new ObjectMapper()
                    .readValue(request.getInputStream(), WtLoginRequest.class);
            return authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            user.getUsername(),
                            user.getPassword(),
                            new ArrayList<>()
                    )
            );
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     * 根据用户登陆成功的信息生成TOKEN
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {


        /*
        *  拼装用来存储到TOEKN内的用户角色
        * */
        String authoritiesString = "";
        List<String> authorities;
        if(authResult.getAuthorities() != null){
            List<String> collect = authResult.getAuthorities()
                    .stream().map(auth -> ((GrantedAuthority) auth).getAuthority()).collect(Collectors.toList());
            authoritiesString = String.join(",",collect);
            authorities = collect;
        }else{
            authorities = new ArrayList<>();
        }

        /*token过期时间*/
        Date expireTime = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(30));

        /*得到TOKEN*/
        String token = WtTokenUtils.createrToken(authResult.getPrincipal().toString(),authorities,expireTime);

        /*返回到头中*/
        response.setHeader("Content-type","application/json;charset=UTF-8");
        response.addHeader(TokenFieldName, token); response.getWriter()
                .append(new ObjectMapper().writeValueAsString(new WtBaseResponse<>(token)));
    }

    /**
     * @param request
     * @param response
     * @param failed
     * @throws IOException
     * @throws ServletException
     *  失败返回失败消息
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        response.setHeader("Content-type","application/json;charset=UTF-8");
        response.getWriter()
                .append(new ObjectMapper().writeValueAsString(new WtBaseResponse<>(1000,failed.getMessage())));
//        super.unsuccessfulAuthentication(request, response, failed);
    }
}
